<?php

namespace app\api\controller;

use app\common\controller\Api;
use app\common\model\Customer as CustomerModel;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use think\Db;

/**
 * 首页接口
 */
class Test extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];

    /**
     * 首页
     *
     */
    public function index()
    {
        $this->success('请求成功');
    }



    /**
     * 合同数据迁移：fa_qingdongams_contract -> fa_contracts
     * - 分页（按 id 递增）迁移，保留原始 id
     * - 字段名/类型转换
     * - 冲突策略：skip/replace/update
     * 请求参数：
     * - batchSize:int 每批大小，默认500
     * - lastId:int 起始ID（上次结束的最后ID），默认0
     * - onConflict:string 冲突策略 skip|replace|update，默认skip
     */
    public function migrateContracts()
    {
     
        $batchSize = (int)$this->request->post('batchSize', 5000);
        $lastId = (int)$this->request->post('lastId',1);
        $onConflict = $this->request->post('on_conflict', 'skip'); // 获取冲突策略

        $migrated = 0;
        $skipped = 0;
        $failed = 0;
        $maxIdThisBatch = $lastId;
        $errors = [];

        // 读取一批
        $rows = Db::name('qingdongams_contract')
            ->where('id', '>=', $lastId)
            ->order('id asc')
            ->limit($batchSize)
            ->select();

     
        if (empty($rows)) {
            $this->success('无可迁移数据', [
                'migrated' => 0,
                'skipped' => 0,
                'failed' => 0,
                'lastId' => $lastId,
                'done' => true,
            ]);
        }

        Db::startTrans();
        try {
            foreach ($rows as $src) {
                $maxIdThisBatch = max($maxIdThisBatch, (int)$src['id']);

                // 字段映射与类型转换
                $target = [];
                $target['id'] = (int)$src['id'];
                $target['contractName'] = isset($src['name']) ? mb_substr((string)$src['name'], 0, 100) : null;
                $target['customer_id'] = isset($src['customer_id']) ? (string)$src['customer_id'] : null; // 目标为 varchar
                $target['contractCode'] = isset($src['num']) ? (string)$src['num'] : null;
                // 审核状态：优先 is_check_success，其次 check_status==2 认为通过
                // if (isset($src['is_check_success'])) {
                //     $target['status'] = (string)((int)$src['is_check_success']);
                // } elseif (isset($src['check_status'])) {
                //     $target['status'] = ((int)$src['check_status'] === 2) ? '1' : '0';
                // } else {
                //     $target['status'] = '0';
                // }
                // 金额缩放至 12,2 风险控制（超过范围时截断）
                if (isset($src['money']) && $src['money'] !== null && $src['money'] !== '') {
                    $amount = (float)$src['money'];
                    if ($amount > 999999999999.99) { $amount = 999999999999.99; }
                    if ($amount < -999999999999.99) { $amount = -999999999999.99; }
                    $target['amount'] = number_format($amount, 2, '.', '');
                } else {
                    $target['amount'] = null;
                }
                $target['sign_date'] = !empty($src['order_date']) ? (string)$src['order_date'] : null; // date->date
                // 时间
                $createdAt = null;
                if (!empty($src['createtime']) && is_numeric($src['createtime'])) {
                    $createdAt = date('Y-m-d H:i:s', (int)$src['createtime']);
                }else{
                    $createdAt = '';
                }
                $updatedAt = null;
                if (!empty($src['updatetime']) && is_numeric($src['updatetime'])) {
                    $updatedAt = date('Y-m-d H:i:s', (int)$src['updatetime']);
                } elseif (!empty($src['last_time'])) {
                    // 源表 last_time 为 datetime
                    $updatedAt = (string)$src['last_time'];
                }
                $target['created_at'] = $createdAt ?: date('Y-m-d H:i:s');
                $target['updated_at'] = $updatedAt ?: $target['created_at'];
                // 进度/状态
                if (isset($src['contract_status'])) {
                    $target['progress'] = (string)$src['contract_status'];
                } elseif (!empty($src['contract_state'])) {
                    $target['progress'] = (string)$src['contract_state'];
                } else {
                    $target['progress'] = null;
                }
                $target['remark'] = isset($src['remarks']) ? (string)$src['remarks'] : null;
                // 附件/证据可选：这里用回执附件占位
                $target['createtime'] = $createdAt; // 目标里也有 createtime(datetime)
                $target['is_delete'] = 0;
                $target['staff_id'] = isset($src['owner_staff_id']) ? (int)$src['owner_staff_id'] : null;
                $target['user_id'] = isset($src['create_staff_id']) ? (int)$src['create_staff_id'] : null;
                $target['deletetime'] = !empty($src['deletetime']) ? (int)$src['deletetime'] : null;
                if($target['deletetime']){
                    $target['is_delete'] = 1;
                }
                $target['create_time'] = $src['createtime'];
                $target['repaid_amount'] = isset($src['receivables_money']) ? (string)$src['receivables_money'] : null;

                try {
                    // 冲突策略处理
                    $exists = Db::name('contracts')->where('id', $target['id'])->find();
                    if ($exists) {
                        $skipped++;
                    } else {
                        // 直接按保留ID插入
                        Db::name('contracts')->insert($target, false);
                        $migrated++;
                    }
                } catch (\Exception $e) {
                    $failed++;
                    $errors[] = [
                        'id' => $target['id'],
                        'msg' => $e->getMessage(),
                    ];
                }
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error('迁移失败：' . $e->getMessage());
        }

        $this->success('迁移完成（本批次）', [
            'migrated' => $migrated,
            'skipped' => $skipped,
            'failed' => $failed,
            'lastId' => $maxIdThisBatch,
            'next' => [
                'lastId' => $maxIdThisBatch,
                'batchSize' => $batchSize,
            ],
            'done' => count($rows) < $batchSize,
            'errors' => $errors,
        ]);
    }
    
    /**
     * 迁移客户数据
     * 从 fa_qingdongams_customer 迁移到 fa_customer_copy
     */
    public function migrateCustomers()
    {
        $batchSize = (int)$this->request->post('batchSize', 5000);
        
        $lastId = (int)$this->request->post('lastId', 1);
        
        $migrated = 0;
        $skipped = 0;
        $failed = 0;
        $maxIdThisBatch = $lastId;
        $errors = [];

        // 读取一批
        $rows = Db::name('qingdongams_customer')
            ->where('id', '>', $lastId)
            ->order('id asc')
            ->limit($batchSize)
            ->select();

        if (empty($rows)) {
            $this->success('无可迁移数据', [
                'migrated' => 0,
                'skipped' => 0,
                'failed' => 0,
                'lastId' => $lastId,
                'done' => true,
            ]);
        }
        
        Db::startTrans();
        try {
            $batchData = []; // 用于批量插入的数据
            
            foreach ($rows as $src) {
                try {
                    $maxIdThisBatch = max($maxIdThisBatch, (int)$src['id']);
                    
                    // 字段映射与类型转换
                    $target = [];
                    $target['id'] = (int)$src['id'];
                    $target['customerName'] = isset($src['name']) ? $src['name'] : null;
                    $target['productName'] = isset($src['main_xswokl']) ? $src['main_xswokl'] : null;
                    $target['uidipin'] = isset($src['main_zcmjhq']) ? $src['main_zcmjhq']: null;
                    $target['batch'] = isset($src['main_zcoudp']) ? $src['main_zcoudp'] : null;
                    $target['orderNo'] = isset($src['main_szjsgl']) ? $src['main_szjsgl'] : null;
                    $target['orgName'] = isset($src['main_ixfdza']) ? $src['main_ixfdza'] : null;
                    $target['guaranteeCompany'] = isset($src['main_aotowv']) ? $src['main_aotowv'] : null;
                    $target['phone'] = isset($src['mobile']) ? mb_substr((string)$src['mobile'], 0, 32) : null;
                    $target['phone1'] = isset($src['main_yifszd']) ? mb_substr((string)$src['main_yifszd'], 0, 32) : null;
                    $target['emergencyPhone'] = isset($src['main_ctvsix']) ? mb_substr((string)$src['main_ctvsix'], 0, 32) : null;
                    $target['idCard'] = isset($src['main_jxcsvi']) ? mb_substr((string)$src['main_jxcsvi'], 0, 32) : null;
                    $target['homeAddress'] = isset($src['main_onqmdp']) ? mb_substr((string)$src['main_onqmdp'], 0, 255) : null;
                    
                    // 沟通状态和起诉状态 - 处理JSON格式
                    if (isset($src['main_jdnvgj']) && !empty($src['main_jdnvgj'])) {
                        $target['communicationStatus'] = $src['main_jdnvgj'];
                    } else {
                        $target['communicationStatus'] = null;
                    }
                    
                    if (isset($src['main_cdcjbm']) && !empty($src['main_cdcjbm'])) {
                        $target['lawsuitStatus'] = $src['main_cdcjbm'];
                    } else {
                        $target['lawsuitStatus'] = null;
                    }

                    if(empty($target['uidipin'])){
                        $target['uidipin'] =isset($src['main_uwonau']) ? $src['main_uwonau']: null;
                    }

                    
                    // 金额字段 - 处理精度转换
                    if (isset($src['main_gfldgo']) && $src['main_gfldgo'] !== null && $src['main_gfldgo'] !== '') {
                        $amount = (float)$src['main_gfldgo'];
                        if ($amount > 99999999.99) { $amount = 99999999.99; }
                        if ($amount < -99999999.99) { $amount = -99999999.99; }
                        $target['backendAmount'] = number_format($amount, 2, '.', '');
                    } else {
                        $target['backendAmount'] = '0.00';
                    }
                    
                    if (isset($src['main_evjtxc']) && $src['main_evjtxc'] !== null && $src['main_evjtxc'] !== '') {
                        $amount = (float)$src['main_evjtxc'];
                        if ($amount > 99999999.99) { $amount = 99999999.99; }
                        if ($amount < -99999999.99) { $amount = -99999999.99; }
                        $target['loanAmount'] = number_format($amount, 2, '.', '');
                    } else {
                        $target['loanAmount'] = '0.00';
                    }
                    
                    if (isset($src['main_xigakp']) && $src['main_xigakp'] !== null && $src['main_xigakp'] !== '') {
                        $amount = (float)$src['main_xigakp'];
                        if ($amount > 99999999.99) { $amount = 99999999.99; }
                        if ($amount < -99999999.99) { $amount = -99999999.99; }
                        $target['repaidInterest'] = number_format($amount, 2, '.', '');
                    } else {
                        $target['repaidInterest'] = null;
                    }
                    
                    if (isset($src['main_uwtxmq']) && $src['main_uwtxmq'] !== null && $src['main_uwtxmq'] !== '') {
                        $amount = (float)$src['main_uwtxmq'];
                        if ($amount > 99999999.99) { $amount = 99999999.99; }
                        if ($amount < -99999999.99) { $amount = -99999999.99; }
                        $target['remainingPrincipal'] = number_format($amount, 2, '.', '');
                    } else {
                        $target['remainingPrincipal'] = '0.00';
                    }
                    
                    if (isset($src['main_shgzzo']) && $src['main_shgzzo'] !== null && $src['main_shgzzo'] !== '') {
                        $amount = (float)$src['main_shgzzo'];
                        if ($amount > 99999999.99) { $amount = 99999999.99; }
                        if ($amount < -99999999.99) { $amount = -99999999.99; }
                        $target['remainingPenalty'] = number_format($amount, 2, '.', '');
                    } else {
                        $target['remainingPenalty'] = '0.00';
                    }
                    
                    // 代偿日期
                    if (!empty($src['main_brkufi'])) {
                        $target['compensationDate'] = (string)$src['main_brkufi'];
                    } else {
                        $target['compensationDate'] = null;
                    }
                    
                    $target['plaintiff'] = isset($src['main_wlevgg']) ? mb_substr((string)$src['main_wlevgg'], 0, 128) : null;
                    
                    // 立案时间
                    if (!empty($src['main_wkijmc'])) {
                        $target['filingTime'] = (string)$src['main_wkijmc'];
                    } else {
                        $target['filingTime'] = null;
                    }
                    
                    $target['mailNo'] = isset($src['main_vnkkvw']) ? mb_substr((string)$src['main_vnkkvw'], 0, 64) : null;
                    
                    // 邮寄日期
                    if (!empty($src['main_esiyoj'])) {
                        $target['mailDate'] = (string)$src['main_esiyoj'];
                    } else {
                        $target['mailDate'] = null;
                    }
                    
                    // 缴费时间
                    if (!empty($src['main_qeihdy'])) {
                        $target['paymentDate'] = (string)$src['main_qeihdy'];
                    } else {
                        $target['paymentDate'] = null;
                    }
                    
                    $target['judgeName'] = isset($src['main_xoqyxf']) ? mb_substr((string)$src['main_xoqyxf'], 0, 64) : null;
                    $target['courtPhone'] = isset($src['main_onbvaa']) ? mb_substr((string)$src['main_onbvaa'], 0, 32) : null;
                    $target['filingCaseNo'] = isset($src['main_zsxpqp']) ? mb_substr((string)$src['main_zsxpqp'], 0, 64) : null;
                    
                    // 开庭时间
                    if (!empty($src['main_iwuhdb'])) {
                        $target['courtTime'] = (string)$src['main_iwuhdb'];
                    } else {
                        $target['courtTime'] = null;
                    }
                    
                    $target['verdictResult'] = isset($src['main_yyibmb']) ? (string)$src['main_yyibmb'] : null;
                    $target['executionCaseNo'] = isset($src['main_sgwlwz']) ? mb_substr((string)$src['main_sgwlwz'], 0, 64) : null;
                    $target['verdictFile'] = isset($src['main_zcuaxj']) ? mb_substr((string)$src['main_zcuaxj'], 0, 255) : null;
                    
                    // 执行时间
                    if (!empty($src['main_ysczhx'])) {
                        $target['executionTime'] = (string)$src['main_ysczhx'];
                    } else {
                        $target['executionTime'] = null;
                    }
                    
                    $target['remark'] = isset($src['main_vwierz']) ? (string)$src['main_vwierz'] : null;
                    
                    // 最后跟进时间
                    if (!empty($src['last_time'])) {
                        $target['lastfollowtime'] = strtotime($src['last_time']);
                        } else {
                        $target['lastfollowtime'] = null;
                    }
                    
                    $target['invoiceAmount'] = null; // 目标表有此字段但源表无对应
                    
                    // 创建时间
                    if (!empty($src['createtime']) && is_numeric($src['createtime'])) {
                        $target['createtime'] = date('Y-m-d H:i:s', (int)$src['createtime']);
                    } else {
                        $target['createtime'] = date('Y-m-d H:i:s');
                    }
                    
                    $target['updatetime'] = !empty($src['updatetime']) ? (int)$src['updatetime'] : null;
                    $target['lastfollowcon'] = isset($src['follow_content']) ? mb_substr((string)$src['follow_content'], 0, 255) : null;
                    $target['lawyer'] = isset($src['main_utabht']) ? mb_substr((string)$src['main_utabht'], 0, 255) : null;
                    $target['courtAddress'] = isset($src['main_nwrgsr']) ? mb_substr((string)$src['main_nwrgsr'], 0, 255) : null;
                    $target['court'] = isset($src['main_kmdegl']) ? mb_substr((string)$src['main_kmdegl'], 0, 255) : null;
                    
                    // 领取时间：源 receivetime(int) -> 目标 recieveDate(datetime)
                    if (!empty($src['receivetime']) && is_numeric($src['receivetime'])) {
                        $target['recieveDate'] = date('Y-m-d H:i:s', (int)$src['receivetime']);
                    } else {
                        $target['recieveDate'] = null;
                    }
                    
                    $target['user_id'] = isset($src['create_staff_id']) ? (int)$src['create_staff_id'] : null;
                    $target['is_claim'] = isset($src['is_seas']) ? ((int)$src['is_seas'] === 0 ? 1 : 0) : 1; // 0=公海1=案源
                    $target['claimtime'] = !empty($src['sea_time']) ? (int)$src['sea_time'] : null;
                    $target['is_delete'] = 0;
                    $target['staff_id'] = isset($src['owner_staff_id']) ? (int)$src['owner_staff_id'] : null;
                    $target['deletetime'] = !empty($src['deletetime']) ? (int)$src['deletetime'] : null;
                    // 立案凭证：main_agivrp 是图片ID（可能为单个ID、逗号分隔、或JSON数组）
                    $target['certificate'] = isset($src['main_agivrp']) && $src['main_agivrp'] !== ''
                        ? $this->resolveFilePathsByIds($src['main_agivrp'])
                        : null;
                    
                    // 代偿金额
                    if (isset($src['main_wetxby']) && $src['main_wetxby'] !== null && $src['main_wetxby'] !== '') {
                        $amount = (float)$src['main_wetxby'];
                        if ($amount > 99999999.99) { $amount = 99999999.99; }
                        if ($amount < -99999999.99) { $amount = -99999999.99; }
                        $target['compensationAmount'] = number_format($amount, 2, '.', '');
                    } else {
                        $target['compensationAmount'] = null;
                    }
                    
                    // 已还本金
                    if (isset($src['main_qiedtk']) && $src['main_qiedtk'] !== null && $src['main_qiedtk'] !== '') {
                        $amount = (float)$src['main_qiedtk'];
                        if ($amount > 99999999.99) { $amount = 99999999.99; }
                        if ($amount < -99999999.99) { $amount = -99999999.99; }
                        $target['repaidAmount'] = number_format($amount, 2, '.', '');
                    } else {
                        $target['repaidAmount'] = null;
                    }
                    
                    // 已还罚息
                    if (isset($src['main_teosja']) && $src['main_teosja'] !== null && $src['main_teosja'] !== '') {
                        $amount = (float)$src['main_teosja'];
                        if ($amount > 99999999.99) { $amount = 99999999.99; }
                        if ($amount < -99999999.99) { $amount = -99999999.99; }
                        $target['repaidPenalty'] = number_format($amount, 2, '.', '');
                    } else {
                        $target['repaidPenalty'] = null;
                    }
                    
                    // 剩余利息
                    if (isset($src['main_rhbouu']) && $src['main_rhbouu'] !== null && $src['main_rhbouu'] !== '') {
                        $amount = (float)$src['main_rhbouu'];
                        if ($amount > 99999999.99) { $amount = 99999999.99; }
                        if ($amount < -99999999.99) { $amount = -99999999.99; }
                        $target['remainingInterest'] = number_format($amount, 2, '.', '');
                    } else {
                        $target['remainingInterest'] = null;
                    }
                    
                    $target['verdict'] = isset($src['main_zcuaxj']) ? mb_substr((string)$src['main_zcuaxj'], 0, 255) : null;
                    // recieveDate 已由 receivetime 映射设置


                    if($src['deletetime']){
                        $target['is_delete'] = 1;
                    }
                    
                    // 检查是否已存在，如果存在则跳过
                    $exists = Db::name('customer')->where('id', $target['id'])->find();
                    if ($exists) {
                        $skipped++;
                    } else {
                        // 添加到批量插入数组
                        $batchData[] = $target;
                    }
                } catch (\Exception $e) {
                    $failed++;
                    $errors[] = [
                        'id' => isset($src['id']) ? $src['id'] : 'unknown',
                        'msg' => '处理记录失败：' . $e->getMessage(),
                        'data' => $src
                    ];
                }
            }
            
            // 批量插入数据
            if (!empty($batchData)) {
                try {
                    $result = Db::name('customer')->insertAll($batchData);
                    if ($result !== false) {
                        $migrated = count($batchData);
                    } else {
                        $failed = count($batchData);
                        $errors[] = [
                            'msg' => '批量插入失败：数据库操作失败',
                            'batchSize' => count($batchData)
                        ];
                    }
                } catch (\Exception $e) {
                    $failed = count($batchData);
                    $errors[] = [
                        'msg' => '批量插入失败：' . $e->getMessage(),
                        'batchSize' => count($batchData)
                    ];
                }
            }
            
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error('迁移事务失败：' . $e->getMessage());
        }
        
        $this->success('迁移完成（本批次）', [
            'migrated' => $migrated,
            'skipped' => $skipped,
            'failed' => $failed,
            'lastId' => $maxIdThisBatch,
            'next' => [
                'lastId' => $maxIdThisBatch,
                'batchSize' => $batchSize,
            ],
            'done' => count($rows) < $batchSize,
            'errors' => $errors,
        ]);
    }
    
    /**
     * 迁移回款计划数据
     * 从 fa_qingdongams_receivables_plan 迁移到 fa_payment_plan_copy
     */
    public function migratePaymentPlans()
    {
        $batchSize = $this->request->post('batchSize', 1000);
        $lastId = $this->request->post('lastId', 0);
        
            $query = Db::name('qingdongams_receivables_plan')
                ->where('id', '>', $lastId)
                ->order('id', 'asc')
                ->limit($batchSize);
            
            $rows = $query->select();
            
            if (empty($rows)) {
                $this->success('没有更多数据需要迁移');
            }
            
            $migrated = 0;
            $skipped = 0;
            $failed = 0;
            $errors = [];
            $maxIdThisBatch = $lastId;
            

                $batchData = []; // 用于批量插入的数据
                foreach ($rows as $src) {
                    // try {
                        $maxIdThisBatch = max($maxIdThisBatch, (int)$src['id']);
                        
                        // 字段映射
                        $target = [
                            'id' => (int)$src['id'],
                            'period' => isset($src['num']) ? (string)$src['num'] : null,
                            'amount' => null, // 计划回款金额
                            'date' => null, // 计划回款日期
                            'method' => isset($src['return_type']) ? (string)$src['return_type'] : null,
                            'status' => '待回款', // 默认状态
                            'staff_id' => isset($src['owner_staff_id']) ? (string)$src['owner_staff_id'] : null,
                            'createtime' => null, // 创建时间
                            'actual_amount' => null, // 已回款金额
                            'remark' => isset($src['remarks']) ? mb_substr((string)$src['remarks'], 0, 255) : null,
                            'contract_id' => isset($src['contract_id']) ? (int)$src['contract_id'] : null,
                            'customer_id' => isset($src['customer_id']) ? (int)$src['customer_id'] : null,
                            'is_delete' => 0,
                            'remind_date' => null, // 提醒日期
                            'remind_days' => isset($src['remind']) ? (int)$src['remind'] : null,
                            'create_time' => isset($src['createtime']) ? (int)$src['createtime'] : null,
                            'create_id' => isset($src['create_staff_id']) ? (int)$src['create_staff_id'] : null,
                            'updatetime' => null, // 更新时间
                            'dept_id' => null,
                            'deletetime' => !empty($src['deletetime']) ? (int)$src['deletetime'] : null,
                            'user_id' => isset($src['create_staff_id']) ? (int)$src['create_staff_id'] : null,
                        ];
                        
                        // 计划回款金额
                        if (isset($src['money']) && $src['money'] !== null && $src['money'] !== '') {
                            $amount = (float)$src['money'];
                            if ($amount > 99999999.99) { $amount = 99999999.99; }
                            if ($amount < -99999999.99) { $amount = -99999999.99; }
                            $target['amount'] = number_format($amount, 2, '.', '');
                        }
                        
                        // 计划回款日期
                        if (!empty($src['return_date'])) {
                            if (is_numeric($src['return_date'])) {
                                $target['date'] = date('Y-m-d H:i:s', (int)$src['return_date']);
                        } else {
                                $target['date'] = date('Y-m-d H:i:s', strtotime($src['return_date']));
                            }
                        }
                        
                        // 已回款金额
                        if (isset($src['receivables_money']) && $src['receivables_money'] !== null && $src['receivables_money'] !== '') {
                            $amount = (float)$src['receivables_money'];
                            if ($amount > 99999999.99) { $amount = 99999999.99; }
                            if ($amount < -99999999.99) { $amount = -99999999.99; }
                            $target['actual_amount'] = number_format($amount, 2, '.', '');
                        }
                        
                        // 回款状态映射
                        if (isset($src['status'])) {
                            switch ((int)$src['status']) {
                                case 0:
                                    $target['status'] = '待回款';
                        break;
                                case 1:
                                    $target['status'] = '已回款';
                        break;
                                case 2:
                                    $target['status'] = '已逾期';
                        break;
                                default:
                                    $target['status'] = '待回款';
                            }
                        }
                        
                        // 创建时间
                        if (!empty($src['createtime']) && is_numeric($src['createtime'])) {
                            $target['createtime'] = date('Y-m-d H:i:s', (int)$src['createtime']);
                        }
                        
                        // 提醒日期
                        if (!empty($src['remind_date'])) {
                            if (is_numeric($src['remind_date'])) {
                                $target['remind_date'] = date('Y-m-d H:i:s', (int)$src['remind_date']);
                            } else {
                                $target['remind_date'] = date('Y-m-d H:i:s', strtotime($src['remind_date']));
                            }
                        }
                        
                        // 更新时间
                        if (!empty($src['updatetime']) && is_numeric($src['updatetime'])) {
                            $target['updatetime'] = date('Y-m-d H:i:s', (int)$src['updatetime']);
                        }
                        
                        // 检查是否已存在，如果存在则跳过
                        $exists = Db::name('payment_plan')->where('id', $target['id'])->find();
                        if ($exists) {
                            $skipped++;
                        } else {
                            // 添加到批量插入数组
                            $batchData[] = $target;
                        }
                   
                }
                
                // 批量插入数据
                if (!empty($batchData)) {
                    // try {
                        $result = Db::name('payment_plan')->insertAll($batchData);
                        if ($result !== false) {
                            $migrated = count($batchData);
                    } else {
                            $failed = count($batchData);
                            $errors[] = [
                                'msg' => '批量插入失败：数据库操作失败',
                                'batchSize' => count($batchData)
                            ];
                        }
                
                }
                
      
            
            $result = [
                'success' => true,
                'message' => '迁移完成',
                'data' => [
                    'migrated' => $migrated,
                    'skipped' => $skipped,
                    'failed' => $failed,
                    'errors' => $errors,
                    'lastId' => $maxIdThisBatch,
                    'hasMore' => count($rows) >= $batchSize,
                    'batchSize' => $batchSize
                ]
            ];
            
            $this->success('迁移完成', $result['data']);
      
    }
    
    /**
     * 迁移回款记录数据
     * 从 fa_qingdongams_receivables 迁移到 fa_payment_record_copy
     */
    public function migratePaymentRecords()
    {
        $batchSize = $this->request->post('batchSize', 1000);
        $lastId = $this->request->post('lastId', 0);
        
      
            // 查询源数据
            $query = Db::name('qingdongams_receivables')
            ->where('id', '>', $lastId)
            ->order('id', 'asc')
            ->limit($batchSize);
        
            $rows = $query->select();
            
            if (empty($rows)) {
                $this->success('没有更多数据需要迁移');
            }
            
            $migrated = 0;
            $skipped = 0;
            $failed = 0;
            $errors = [];
            $maxIdThisBatch = $lastId;
            
    
        $batchData = []; // 用于批量插入的数据
        foreach ($rows as $src) {
            // try {
            $maxIdThisBatch = max($maxIdThisBatch, (int)$src['id']);
            
            // 字段映射
            $target = [
                'id' => (int)$src['id'],
                'code' => isset($src['number']) ? mb_substr((string)$src['number'], 0, 32) : null,
                'customer' => null, // 需要从customer表查询客户名称
                'contract' => null, // 需要从contracts表查询合同编号
                'date' => null, // 回款日期
                'amount' => null, // 回款金额
                'method' => isset($src['return_type']) ? mb_substr((string)$src['return_type'], 0, 16) : null,
                'lawyer' => isset($src['main_suobap']) ? mb_substr((string)$src['main_suobap'], 0, 32) : null,
                'status' => '已回款', // 默认状态
                'manager' => null, // 需要从user表查询负责人姓名
                'plan' => null, // 需要从payment_plan表查询计划信息
                'image' => null,
                'createtime' => null, // 创建时间
                'customer_id' => isset($src['customer_id']) ? (int)$src['customer_id'] : null,
                'contract_id' => isset($src['contract_id']) ? (int)$src['contract_id'] : null,
                'staff_id' => isset($src['owner_staff_id']) ? (int)$src['owner_staff_id'] : null,
                'remark' => isset($src['remarks']) ? mb_substr((string)$src['remarks'], 0, 255) : null,
                'plan_id' => isset($src['plan_id']) ? (int)$src['plan_id'] : null,
                'account_id' => isset($src['account_id']) ? (int)$src['account_id'] : null,
                'user_id' => isset($src['create_staff_id']) ? (int)$src['create_staff_id'] : null,
                'payname' => isset($src['main_tvzfic']) ? mb_substr((string)$src['main_tvzfic'], 0, 255) : null,
                'create_time' => isset($src['createtime']) ? (int)$src['createtime'] : null,
                'is_delete' => 0,
                'loanno' => isset($src['main_qexsuj']) ? (string)$src['main_qexsuj'] : null,
                'deduction_materials' => isset($src['main_bftbvt']) ? (string)$src['main_bftbvt'] : null,
                'register_date' => null, // 登记日期
                'productName' => isset($src['main_wpyejz']) ? mb_substr((string)$src['main_wpyejz'], 0, 255) : null,
                'registrationDate' => null, // 登记日期
                'deletetime' => !empty($src['deletetime']) ? (int)$src['deletetime'] : null,
                'registration_date' => null, // 登记日期
            ];

            // 回款信息截图：main_mbrjuq 为英文逗号分隔的图片ID字符串，转换为图片路径JSON数组
            if (isset($src['main_mbrjuq']) && $src['main_mbrjuq'] !== '') {
                $target['image'] = $this->resolveFilePathsByIds($src['main_mbrjuq']);
            }
            //京东材料

            if (isset($src['main_bftbvt']) && $src['main_bftbvt'] !== '') {
                $target['deduction_materials'] = $this->resolveFilePathsByIds($src['main_bftbvt']);
            }

            if (!empty($src['deletetime']) ) {
                    $target['is_delete'] = 1;
            }
                
            
            // 回款日期
            if (!empty($src['return_time'])) {
                if (is_numeric($src['return_time'])) {
                    $target['date'] = date('Y-m-d H:i:s', (int)$src['return_time']);
                    } else {
                    $target['date'] = date('Y-m-d H:i:s', strtotime($src['return_time']));
                }
            }
            
            // 回款金额
            if (isset($src['money']) && $src['money'] !== null && $src['money'] !== '') {
                $amount = (float)$src['money'];
                if ($amount > 99999999.99) { $amount = 99999999.99; }
                if ($amount < -99999999.99) { $amount = -99999999.99; }
                $target['amount'] = number_format($amount, 2, '.', '');
            }
            

            
            // 创建时间
            if (!empty($src['createtime']) && is_numeric($src['createtime'])) {
                $target['createtime'] = date('Y-m-d H:i:s', (int)$src['createtime']);
            }
            
            // 登记日期
            if (!empty($src['main_mvjbpk'])) {
                if (is_numeric($src['main_mvjbpk'])) {
                    $target['register_date'] = date('Y-m-d H:i:s', (int)$src['main_mvjbpk']);
                    $target['registrationDate'] = date('Y-m-d H:i:s', (int)$src['main_mvjbpk']);
                    $target['registration_date'] = date('Y-m-d H:i:s', (int)$src['main_mvjbpk']);
            } else {
                    $target['register_date'] = date('Y-m-d H:i:s', strtotime($src['main_mvjbpk']));
                    $target['registrationDate'] = date('Y-m-d H:i:s', strtotime($src['main_mvjbpk']));
                    $target['registration_date'] = date('Y-m-d H:i:s', strtotime($src['main_mvjbpk']));
                }
            }
            
            // 检查是否已存在，如果存在则跳过
            $exists = Db::name('payment_record')->where('id', $target['id'])->find();
            if ($exists) {
                $skipped++;
                } else {
                // 添加到批量插入数组
                $batchData[] = $target;
            }
           
        }
        
        // 批量插入数据
        if (!empty($batchData)) {
            // try {
            $result = Db::name('payment_record')->insertAll($batchData);
            if ($result !== false) {
                $migrated = count($batchData);
            } else {
                $failed = count($batchData);
                $errors[] = [
                    'msg' => '批量插入失败：数据库操作失败',
                    'batchSize' => count($batchData)
                ];
            }
           
        }
        
  
        
        $result = [
            'success' => true,
            'message' => '迁移完成',
            'data' => [
                'migrated' => $migrated,
                'skipped' => $skipped,
                'failed' => $failed,
                'errors' => $errors,
                'lastId' => $maxIdThisBatch,
                'hasMore' => count($rows) >= $batchSize,
                'batchSize' => $batchSize
            ]
        ];
        
        $this->success('迁移完成', $result['data']);
        
    }

    /**
     * 迁移跟进记录数据
     * 从 fa_qingdongams_record 迁移到 fa_follow
     */
    public function migrateFollows()
    {
        $batchSize = $this->request->post('batchSize', 1000);
        $lastId = $this->request->post('lastId', 0);
        
        try {
            // 查询源数据
            $query = Db::name('qingdongams_record')
                ->where('id', '>', $lastId)
                ->order('id', 'asc')
                ->limit($batchSize);
            
            $rows = $query->select();
            
            if (empty($rows)) {
                $this->success('没有更多数据需要迁移');
            }
            
            $migrated = 0;
            $skipped = 0;
            $failed = 0;
            $errors = [];
            $maxIdThisBatch = $lastId;
            
            $batchData = []; // 用于批量插入的数据
            foreach ($rows as $src) {
                try {
                    $maxIdThisBatch = max($maxIdThisBatch, (int)$src['id']);
                    
                    // 字段映射
                    $target = [
                        'id' => (int)$src['id'],
                        'follow_type' => isset($src['follow_type']) ? mb_substr((string)$src['follow_type'], 0, 50) : null,
                        'remark' => isset($src['content']) ? mb_substr((string)$src['content'], 0, 255) : null,
                        'followtime' => null, // 跟进时间
                        'creator' => null, // 需要从user表查询创建人姓名
                        'images' => null, // 证据图片
                        'customer_id' => null, // 客户ID
                        'communication_status' => isset($src['main_samncj']) ? mb_substr((string)$src['main_samncj'], 0, 255) : null,
                        'updatetime' => isset($src['updatetime']) ? (int)$src['updatetime'] : null,
                        'createtime' => isset($src['createtime']) ? (int)$src['createtime'] : null,
                        'user_id' => isset($src['create_staff_id']) ? (int)$src['create_staff_id'] : null,
                        'is_delete' => 0,
                        'staff_id' => isset($src['owner_staff_id']) ? (int)$src['owner_staff_id'] : null,
                        'nexttime' => null, // 下次跟进时间
                        'deletetime' => !empty($src['deletetime']) ? (int)$src['deletetime'] : null,
                    ];
                    
                    // 如果 deletetime 有值，无论 relation_type 是多少，都将 is_delete 设置为 1
                    if (!empty($src['deletetime'])) {
                        $target['is_delete'] = 1;
                    }
                    
                    // 如果 relation_type != 1，则将 is_delete 设置为 1
                    // 如果 deletetime 没有值，则设置为 1746860133
                    if ($src['relation_type'] != 1) {
                        $target['is_delete'] = 1;
                        if (empty($src['deletetime'])) {
                            $target['deletetime'] = 1746860133;
                        }
                    }
                    
                    // 跟进时间
                    if (!empty($src['main_jfmexe'])) {
                        if (is_numeric($src['main_jfmexe'])) {
                            $target['followtime'] = date('Y-m-d H:i:s', (int)$src['main_jfmexe']);
        } else {
                            $target['followtime'] = date('Y-m-d H:i:s', strtotime($src['main_jfmexe']));
                        }
                    } elseif (!empty($src['follow_time'])) {
                        if (is_numeric($src['follow_time'])) {
                            $target['followtime'] = date('Y-m-d H:i:s', (int)$src['follow_time']);
                        } else {
                            $target['followtime'] = date('Y-m-d H:i:s', strtotime($src['follow_time']));
                        }
                    }
                    
                    // 下次跟进时间
                    if (!empty($src['next_time'])) {
                        if (is_numeric($src['next_time'])) {
                            $target['nexttime'] = date('Y-m-d H:i:s', (int)$src['next_time']);
                        } else {
                            $target['nexttime'] = date('Y-m-d H:i:s', strtotime($src['next_time']));
                        }
                    }
                    
                    // 客户ID：根据关联类型确定
                    if ($src['relation_type'] == 1 && !empty($src['relation_id'])) {
                        $target['customer_id'] = (int)$src['relation_id'];
                    }
                    
                    // 证据图片：main_cqmyhk 为英文逗号分隔的图片ID字符串，转换为图片路径JSON数组
                    if (isset($src['main_cqmyhk']) && $src['main_cqmyhk'] !== '') {
                        $target['images'] = $this->resolveFilePathsByIds($src['main_cqmyhk']);
                    }
                    
                    // 检查是否已存在，如果存在则跳过
                    $exists = Db::name('follow')->where('id', $target['id'])->find();
                    if ($exists) {
                        $skipped++;
                    } else {
                        // 添加到批量插入数组
                        $batchData[] = $target;
                    }
                    
                } catch (Exception $e) {
                    $failed++;
                    $errors[] = [
                        'id' => $src['id'],
                        'msg' => $e->getMessage(),
                        'data' => $src
                    ];
                }
            }
            
            // 批量插入数据
            if (!empty($batchData)) {
                try {
                    $result = Db::name('follow')->insertAll($batchData);
                    if ($result !== false) {
                        $migrated = count($batchData);
                    } else {
                        $failed = count($batchData);
                        $errors[] = [
                            'msg' => '批量插入失败：数据库操作失败',
                            'batchSize' => count($batchData)
                        ];
                    }
                } catch (Exception $e) {
                    $failed = count($batchData);
                    $errors[] = [
                        'msg' => '批量插入异常：' . $e->getMessage(),
                        'batchSize' => count($batchData),
                        'trace' => $e->getTraceAsString()
                    ];
                }
            }
            
            $result = [
                'success' => true,
                'message' => '迁移完成',
                'data' => [
                    'migrated' => $migrated,
                    'skipped' => $skipped,
                    'failed' => $failed,
                    'errors' => $errors,
                    'lastId' => $maxIdThisBatch,
                    'hasMore' => count($rows) >= $batchSize,
                    'batchSize' => $batchSize
                ]
            ];
            
            $this->success('迁移完成', $result['data']);
            
        } catch (Exception $e) {
            $this->error('迁移失败：' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);
        }
    }


    /**
     * 迁移部门数据
     * 从 fa_qingdong_auth_group 迁移到 fa_department_copy
     */
    public function migrateDepartments()
    {
        $batchSize = $this->request->post('batchSize', 1000);
        $lastId = $this->request->post('lastId', 0);
        
        // 查询源数据
        $query = Db::name('qingdong_auth_group')
            ->where('id', '>', $lastId)
            ->order('id', 'asc')
            ->limit($batchSize);
        
        $rows = $query->select();
        
        if (empty($rows)) {
            $this->success('没有更多数据需要迁移');
        }
        
        $migrated = 0;
        $skipped = 0;
        $failed = 0;
        $errors = [];
        $maxIdThisBatch = $lastId;
        
        $batchData = []; // 用于批量插入的数据
        foreach ($rows as $src) {
            $maxIdThisBatch = max($maxIdThisBatch, (int)$src['id']);
            
            // 字段映射：从权限组转换为部门结构
            $target = [
                'id' => (int)$src['id'],
                'parent_id' => isset($src['pid']) ? (int)$src['pid'] : 0,
                'title' => isset($src['name']) ? mb_substr((string)$src['name'], 0, 100) : '未命名部门',
                'status' => 1, // 默认启用
                'weigh' => 0, // 默认排序权重
                'createtime' => null, // 创建时间
                'updatetime' => null, // 更新时间
                'is_delete' => 0, // 默认未删除
            ];
            
            // 状态映射：根据源表状态设置部门状态
            if (isset($src['status']) && !empty($src['status'])) {
                $status = strtolower((string)$src['status']);
                if (in_array($status, ['disabled', '0', 'false', '禁用', '停用'])) {
                    $target['status'] = 0; // 禁用
                } else {
                    $target['status'] = 1; // 启用
                }
            }
            
            // 创建时间
            if (!empty($src['createtime']) && is_numeric($src['createtime'])) {
                $target['createtime'] = (int)$src['createtime'];
            }
            
            // 更新时间
            if (!empty($src['updatetime']) && is_numeric($src['updatetime'])) {
                $target['updatetime'] = (int)$src['updatetime'];
            }
            
            // 检查是否已存在，如果存在则跳过
            $exists = Db::name('department')->where('id', $target['id'])->find();
            if ($exists) {
                $skipped++;
            } else {
                // 添加到批量插入数组
                $batchData[] = $target;
            }
        }
        
        // 批量插入数据
        if (!empty($batchData)) {
            $result = Db::name('department')->insertAll($batchData);
            if ($result !== false) {
                $migrated = count($batchData);
            } else {
                $failed = count($batchData);
                $errors[] = [
                    'msg' => '批量插入失败：数据库操作失败',
                    'batchSize' => count($batchData)
                ];
            }
        }
        
        $result = [
            'success' => true,
            'message' => '迁移完成',
            'data' => [
                'migrated' => $migrated,
                'skipped' => $skipped,
                'failed' => $failed,
                'errors' => $errors,
                'lastId' => $maxIdThisBatch,
                'hasMore' => count($rows) >= $batchSize,
                'batchSize' => $batchSize
            ]
        ];
        
        $this->success('迁移完成', $result['data']);
    }

    /**
     * 迁移员工数据
     * 从 fa_qingdongams_staff 迁移到 fa_user
     */
    public function migrateStaff()
    {
        $batchSize = $this->request->post('batchSize', 1000);
        $lastId = $this->request->post('lastId', 0);
        
        // 查询源数据
        $query = Db::name('qingdongams_staff')
            ->where('id', '>', $lastId)
            ->order('id', 'asc')
            ->limit($batchSize);
        
        $rows = $query->select();
        
        if (empty($rows)) {
            $this->success('没有更多数据需要迁移');
        }
        
        $migrated = 0;
        $skipped = 0;
        $failed = 0;
        $errors = [];
        $maxIdThisBatch = $lastId;
        
        $batchData = []; // 用于批量插入的数据
        foreach ($rows as $src) {
            $maxIdThisBatch = max($maxIdThisBatch, (int)$src['id']);
            
            // 字段映射：从员工表转换为用户表
            $target = [
                'id' => (int)$src['id'],
                'group_id' => 0, // 默认组别ID
                'name' => isset($src['name']) ? mb_substr((string)$src['name'], 0, 255) : null,
                'username' => isset($src['mobile']) ? mb_substr((string)$src['mobile'], 0,  50) : '',
                'nickname' => isset($src['nickname']) ? mb_substr((string)$src['nickname'], 0, 50) : '',
                'password' => isset($src['password']) ? (string)$src['password'] : '',
                'salt' => isset($src['salt']) ? (string)$src['salt'] : '',
                'email' => isset($src['email']) ? mb_substr((string)$src['email'], 0, 100) : '',
                'mobile' => isset($src['mobile']) ? mb_substr((string)$src['mobile'], 0, 50) : '',
                'avatar' => isset($src['img']) ? (string)$src['img'] : '',
                'level' => 0, // 默认等级
                'gender' => '0', // 默认性别
                'birthday' => null, // 生日
                'bio' => '', // 格言
                'money' => '0.00', // 余额
                'score' => 0, // 积分
                'successions' => 1, // 连续登录天数
                'maxsuccessions' => 1, // 最大连续登录天数
                'prevtime' => null, // 上次登录时间
                'logintime' => null, // 登录时间
                'loginip' => '', // 登录IP
                'loginfailure' => 0, // 失败次数
                'loginfailuretime' => null, // 最后登录失败时间
                'joinip' => '', // 加入IP
                'jointime' => null, // 加入时间
                'createtime' => null, // 创建时间
                'updatetime' => null, // 更新时间
                'token' => '', // Token
                'status' => 'normal', // 状态
                'verification' => '', // 验证
                'role_id' => null, // 角色ID
                'department_id' => $src['group_ids'], // 部门ID
                'leader_id' => null, // 上级
                'is_delete' => 0, // 是否删除
                'superior_id' => null, // 上级ID
            ];
            
            // 性别映射
            if (isset($src['sex'])) {
                switch ((int)$src['sex']) {
                    case 1:
                        $target['gender'] = 'M'; // 男
                        break;
                    case 2:
                        $target['gender'] = 'F'; // 女
                        break;
                    default:
                        $target['gender'] = '0'; // 未知
                }
            }
            
            // 状态映射
            if (isset($src['status'])) {
                switch ((int)$src['status']) {
                    case 0:
                        $target['status'] = 'hidden'; // 待审核
                        break;
                    case 1:
                        $target['status'] = 'normal'; // 启用
                        break;
                    case 2:
                        $target['status'] = 'hidden'; // 禁用
                        break;
                    default:
                        $target['status'] = 'normal';
                }
            }
            
            // 角色ID映射
            if (isset($src['role'])) {
                $target['role_id'] = (int)$src['role'];
            }
          
            // 部门ID
            if (isset($src['department_id'])) {
                $target['department_id'] = (int)$src['department_id'];
            }
            
            // 上级ID
            if (isset($src['parent_id'])) {
                $target['leader_id'] = (int)$src['parent_id'];
                $target['superior_id'] = (int)$src['parent_id'];
            }
            
            // 创建时间
            if (!empty($src['createtime']) && is_numeric($src['createtime'])) {
                $target['createtime'] = (int)$src['createtime'];
                $target['jointime'] = (int)$src['createtime'];
            }
            
            // 更新时间
            if (!empty($src['updatetime']) && is_numeric($src['updatetime'])) {
                $target['updatetime'] = (int)$src['updatetime'];
            }
            
            // 最后在线时间
            if (!empty($src['last_online_time']) && is_numeric($src['last_online_time'])) {
                $target['logintime'] = (int)$src['last_online_time'];
            }
            
            // 检查是否已存在，如果存在则跳过
            $exists = Db::name('user')->where('id', $target['id'])->find();
            if ($exists) {
                $skipped++;
            } else {
                // 添加到批量插入数组
                $batchData[] = $target;
            }
        }
        
        // 批量插入数据
        if (!empty($batchData)) {
            $result = Db::name('user')->insertAll($batchData);
            if ($result !== false) {
                $migrated = count($batchData);
            } else {
                $failed = count($batchData);
                $errors[] = [
                    'msg' => '批量插入失败：数据库操作失败',
                    'batchSize' => count($batchData)
                ];
            }
        }
        
        $result = [
            'success' => true,
            'message' => '迁移完成',
            'data' => [
                'migrated' => $migrated,
                'skipped' => $skipped,
                'failed' => $failed,
                'errors' => $errors,
                'lastId' => $maxIdThisBatch,
                'hasMore' => count($rows) >= $batchSize,
                'batchSize' => $batchSize
            ]
        ];
        
        $this->success('迁移完成', $result['data']);
    }

    /**
     * 迁移账户数据
     * 从 fa_qingdongams_account 迁移到 fa_account
     */
    public function migrateAccounts()
    {
        $batchSize = $this->request->post('batchSize', 1000);
        $lastId = $this->request->post('lastId', 0);
        
        // 查询源数据
        $query = Db::name('qingdongams_account')
            ->where('id', '>', $lastId)
            ->order('id', 'asc')
            ->limit($batchSize);
        
        $rows = $query->select();
        
        if (empty($rows)) {
            $this->success('没有更多数据需要迁移');
        }
        
        $migrated = 0;
        $skipped = 0;
        $failed = 0;
        $errors = [];
        $maxIdThisBatch = $lastId;
        
        $batchData = []; // 用于批量插入的数据
        foreach ($rows as $src) {
            $maxIdThisBatch = max($maxIdThisBatch, (int)$src['id']);
            
            // 字段映射：从源账户表转换为目标账户表
            $target = [
                'id' => (int)$src['id'],
                'bank' => isset($src['deposit']) ? (string)$src['deposit'] : null,
                'account_name' => isset($src['name']) ? (string)$src['name'] : null,
                'account_no' => isset($src['account']) ? (string)$src['account'] : null,
                'balance' => isset($src['money']) ? number_format((float)$src['money'], 2, '.', '') : '0.00',
                'account_type' => isset($src['type']) ? (string)$src['type'] : 'public',
                'status' => isset($src['status']) ? (int)$src['status'] : 1,
                'income' => '0.00', // 默认收入
                'expense' => '0.00', // 默认支出
                'createtime' => null, // 创建时间
                'updatetime' => null, // 更新时间
                'is_delete' => 0, // 是否删除
                'deletetime' => null, // 删除时间
                'partya' => null, // 甲方
            ];
            
            // 账户类型映射
            if (isset($src['type'])) {
                switch ($src['type']) {
                    case 'public':
                        $target['account_type'] = 'public'; // 公账
                        break;
                    case 'private':
                        $target['account_type'] = 'private'; // 私户
                        break;
                    default:
                        $target['account_type'] = 'public'; // 默认公账
                }
            }
            
            // 状态映射
            if (isset($src['status'])) {
                switch ((int)$src['status']) {
                    case 0:
                        $target['status'] = 0; // 禁用
                        break;
                    case 1:
                        $target['status'] = 1; // 正常
                        break;
                    default:
                        $target['status'] = 1; // 默认正常
                }
            }
            
            // 余额处理
            if (isset($src['money']) && is_numeric($src['money'])) {
                $target['balance'] = number_format((float)$src['money'], 2, '.', '');
            }
            
            // 创建时间
            if (!empty($src['createtime']) && is_numeric($src['createtime'])) {
                $target['createtime'] = date('Y-m-d H:i:s', (int)$src['createtime']);
            } else {
                $target['createtime'] = date('Y-m-d H:i:s'); // 当前时间
            }
            
            // 更新时间
            if (!empty($src['updatetime']) && is_numeric($src['updatetime'])) {
                $target['updatetime'] = date('Y-m-d H:i:s', (int)$src['updatetime']);
            } else {
                $target['updatetime'] = date('Y-m-d H:i:s'); // 当前时间
            }
            
            // 删除时间
            if (!empty($src['deletetime']) && is_numeric($src['deletetime'])) {
                $target['deletetime'] = (int)$src['deletetime'];
                $target['is_delete'] = 1; // 如果原表有删除时间，标记为已删除
            }
            
            // 检查是否已存在，如果存在则跳过
            $exists = Db::name('account')->where('id', $target['id'])->find();
            if ($exists) {
                $skipped++;
            } else {
                // 添加到批量插入数组
                $batchData[] = $target;
            }
        }
        
        // 批量插入数据
        if (!empty($batchData)) {
            try {
                $result = Db::name('account')->insertAll($batchData);
                if ($result !== false) {
                    $migrated = count($batchData);
                } else {
                    $failed = count($batchData);
                    $errors[] = [
                        'msg' => '批量插入失败：数据库操作失败',
                        'batchSize' => count($batchData)
                    ];
                }
            } catch (\Exception $e) {
                $failed = count($batchData);
                $errors[] = [
                    'msg' => '批量插入失败：' . $e->getMessage(),
                    'batchSize' => count($batchData)
                ];
            }
        }
        
        $result = [
            'success' => true,
            'message' => '迁移完成',
            'data' => [
                'migrated' => $migrated,
                'skipped' => $skipped,
                'failed' => $failed,
                'errors' => $errors,
                'lastId' => $maxIdThisBatch,
                'hasMore' => count($rows) >= $batchSize,
                'batchSize' => $batchSize
            ]
        ];
        
        $this->success('迁移完成', $result['data']);
    }

    /**
     * 迁移操作日志数据
     * 从 fa_qingdongams_operation_log 迁移到 fa_operation_log
     */
    public function migrateOperationLogs()
    {
        $batchSize = (int)$this->request->post('batchSize', 5000);
        $lastId = (int)$this->request->post('lastId', 1);

        $migrated = 0;
        $skipped = 0;
        $failed = 0;
        $maxIdThisBatch = $lastId;
        $errors = [];

        $rows = Db::name('qingdongams_operation_log')
            ->where('id', '>=', $lastId)
            ->order('id asc')
            ->limit($batchSize)
            ->select();

        if (empty($rows)) {
            $this->success('无可迁移数据', [
                'migrated' => 0,
                'skipped' => 0,
                'failed' => 0,
                'lastId' => $lastId,
                'done' => true,
            ]);
        }

        Db::startTrans();
        try {
            foreach ($rows as $src) {
                $maxIdThisBatch = max($maxIdThisBatch, (int)$src['id']);

                $target = [];
                $target['id'] = (int)$src['id'];
                $relationType = isset($src['relation_type']) ? (int)$src['relation_type'] : null;
                $relationId = isset($src['relation_id']) ? (int)$src['relation_id'] : 0;
                $target['customer_id'] = ($relationType === 1 && $relationId > 0) ? $relationId : 0;
                $target['relation_id'] = $relationId;
                $target['relation_type'] = $relationType;
                $target['user_id'] = isset($src['operation_id']) ? (int)$src['operation_id'] : null;
                $target['content'] = isset($src['content']) ? mb_substr((string)$src['content'], 0, 255) : null;
                $target['createtime'] = (!empty($src['createtime']) && is_numeric($src['createtime'])) ? date('Y-m-d H:i:s', (int)$src['createtime']) : null;
                $target['ip'] = isset($src['ip']) ? (string)$src['ip'] : null;

                try {
                    $exists = Db::name('operation_log')->where('id', $target['id'])->find();
                    if ($exists) {
                        $skipped++;
                    } else {
                        Db::name('operation_log')->insert($target, false);
                        $migrated++;
                    }
                } catch (\Exception $e) {
                    $failed++;
                    $errors[] = [
                        'id' => $target['id'],
                        'msg' => $e->getMessage(),
                    ];
                }
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error('迁移失败：' . $e->getMessage());
        }

        $this->success('迁移完成（本批次）', [
            'migrated' => $migrated,
            'skipped' => $skipped,
            'failed' => $failed,
            'lastId' => $maxIdThisBatch,
            'next' => [
                'lastId' => $maxIdThisBatch,
                'batchSize' => $batchSize,
            ],
            'done' => count($rows) < $batchSize,
            'errors' => $errors,
        ]);
    }

    /**
     * 将图片ID集合解析为文件路径JSON数组
     * @param mixed $ids 可以是数字、逗号分隔字符串、或JSON数组字符串
     * @return string|null JSON数组字符串，如 ["/uploads/...","/uploads/..."]，如果无有效图片则返回null
     */
    private function resolveFilePathsByIds($ids)
    {
        // 规范化为数组
        $idArray = [];
        if (is_array($ids)) {
            $idArray = $ids;
        } elseif (is_string($ids)) {
            $trim = trim($ids);
            if ($trim === '') {
                $idArray = [];
            } else {
                // 尝试JSON
                $maybeJson = null;
                if ($trim[0] === '[' || $trim[0] === '"' || $trim[0] === '{') {
                    $maybeJson = json_decode($trim, true);
                }
                if (is_array($maybeJson)) {
                    $idArray = $maybeJson;
                } else {
                    // 逗号分隔
                    $idArray = array_map('trim', explode(',', $trim));
                }
            }
        } elseif (is_numeric($ids)) {
            $idArray = [(string)$ids];
        }

        // 仅保留数字ID
        $idArray = array_values(array_filter($idArray, function ($v) {
            return is_numeric($v) && (int)$v > 0;
        }));

        if (empty($idArray)) {
            return null;
        }

        // 查询文件路径
        $paths = Db::name('qingdongams_file')
            ->where('id', 'in', $idArray)
            ->orderRaw("FIELD(id, '" . implode("','", array_map('intval', $idArray)) . "')")
            ->column('file_path');

        if (empty($paths)) {
            return null;
        }
        // 输出JSON数组（保留斜杠）
        return json_encode(array_values($paths), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    }
}
